package zunge.tools;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Random;

public class Tools {

	public static <A,B> void saveMap(HashMap<A,B> map, String file) throws IOException{
		BufferedWriter bw = new BufferedWriter(new FileWriter(file));
		for(Entry<A,B> entry:map.entrySet()){
			bw.write(entry.getKey()+"\t"+entry.getValue()+"\n");
		}
		bw.close();
	}
	
	public static HashMap<Long,Integer> loadMap(String file) throws IOException{
		HashMap<Long,Integer> map = new HashMap<Long,Integer>();
		BufferedReader br = new BufferedReader(new FileReader(file));
		String line;
		while((line=br.readLine())!=null){
			String[] frags = line.split("\t");
			map.put(Long.parseLong(frags[0]), Integer.parseInt(frags[1]));
		}
		br.close();
		return map;
	}
	public static void saveSet(HashSet<Integer> set, String file) throws IOException{
		BufferedWriter bw = new BufferedWriter(new FileWriter(file));
		for(Integer i:set){
			bw.write(i+"\n");
		}
		bw.close();
	}
	public static HashSet<Integer> loadSet(String file) throws IOException{
		HashSet<Integer> set = new HashSet<Integer>();
		BufferedReader br = new BufferedReader(new FileReader(file));
		String line;
		while((line=br.readLine())!=null){
			set.add(Integer.parseInt(line));
		}
		br.close();
		return set;
	}
	
	
	
	static Random random = null;
	/** min <= n < max */
	public static double unifRand(double min, double max){
		if(random==null){random = new Random();}
		return min + (max-min)*random.nextDouble();
	}
	
	/** min <= N < max */
	public static int unifRandInt(int min, int max){
		return min + (int)(Math.random() * ((max - min)));
	}
	
	/** return k-max indices of a vector*/
	public static List<Integer> getTopK(double[] vector, int k, boolean desc){
		List<WeightedItem> wis = new ArrayList<WeightedItem>(vector.length);
		for(int i = 0;i < vector.length;++i){wis.add(new WeightedItem(vector[i],i));}
		Collections.sort(wis);
		List<Integer> ret = new ArrayList<Integer>();
		for(int i = 0;i < vector.length && i < k;++i){
			if(desc){
				ret.add(wis.get(wis.size()-1-i).index);
			}else{
				ret.add(wis.get(i).index);
			}
		}
		return ret;
	}
	static class WeightedItem implements Comparable<WeightedItem>{
		public Double data;
		public int index;
		public WeightedItem(double data, int index){
			this.data = data;
			this.index = index;
		}
		@Override
		public int compareTo(WeightedItem arg0) {
			return this.data.compareTo(arg0.data);
		}		
	}
	
	
	/** Format yyyyMMdd, HHmmss into "yyyy-MM-dd HH:mm:ss" */
	public static String formatDatetime(String yyyyMMdd, String HHmmss){
		char[] c1 = yyyyMMdd.toCharArray();
		char[] c2 = HHmmss.toCharArray();
		char[] c = new char[19]; //"yyyy-MM-dd HH:mm:ss"
		c[0] = c1[0]; c[1] = c1[1]; c[2] = c1[2]; c[3] = c1[3];
		c[4] = '-';
		c[5] = c1[4]; c[6] = c1[5];
		c[7] = '-';
		c[8] = c1[6]; c[9] = c1[7];
		c[10] = ' ';
		c[11] = c2[0]; c[12] = c2[1];
		c[13] = ':';
		c[14] = c2[2]; c[15] = c2[3];
		c[16] = ':';
		c[17] = c2[4]; c[18] = c2[5];
		return new String(c);
	}
	
	/**
	 * Get if the Nth bit (from right) is 1
	 */
	public static boolean getNBitFromRight(int i, int n){
		int mask = 1 << (n-1);
		return ((i & mask)==0)?false:true;
	}
	
	public static HashSet<Integer> getRandomSelections(int size, double ratio){
		List<Integer> ints = new ArrayList<Integer>();
		for(int i = 0;i < size;++i){ints.add(i);}
		Collections.shuffle(ints);
		HashSet<Integer> ret = new HashSet<Integer>();
		int selections = (int)Math.max(1, size * ratio);
		for(int i = 0;i < selections;++i){ret.add(ints.get(i));}
		return ret;
	}
	
	
	public static double getAverage(double[] data){
		double avg = 0;
		for(int i = 0;i < data.length;++i){avg+=data[i];}
		return avg/data.length;
	}
	public static double getVariance(double[] data){
		double avg = 0;
		for(int i = 0;i < data.length;++i){avg+=data[i];}
		avg /= data.length;
		double total = 0;
		for(int i = 0;i < data.length;++i){total+=(data[i]-avg)*(data[i]-avg);}
		return Math.sqrt(total/data.length);
	}
}
